package middle_man;


import java.util.ArrayList;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;

public class Worker extends Thread {
	private LinkedBlockingQueue<Request> Q;
	private Connection connection;
	private boolean _terminate = false;
	private String host;
	
	public Worker(LinkedBlockingQueue<Request> _Q, String db_host, String db_database) {
		Q = _Q;
		connection = DB.connect(db_host, db_database);
		host = db_host;
	}
	
	public void terminate() {
		_terminate = true;
	}
	
	private void DoRequest(Request r) {
		Statement stmt = null;
		ResultSet rs = null;
		long start_time = 0L, stop_time = 0L;
		try {
			stmt = connection.createStatement();
			if(r.getSqlQuery().indexOf("create or replace view") == -1) {
				// Usual query
				start_time = System.currentTimeMillis();
				rs = stmt.executeQuery(r.getSqlQuery());
				stop_time = System.currentTimeMillis();
			} else {
				// A query which needs a view
				String [] pieces = r.getSqlQuery().split(";");
				stmt.execute(pieces[0] + ";");
				stmt.close();
				
				stmt = connection.createStatement();
				start_time = System.currentTimeMillis();
				rs = stmt.executeQuery(pieces[1] + ";");
				stop_time = System.currentTimeMillis();
			}
			ResultSetMetaData rsmd = rs.getMetaData();
            int columnsCount = rsmd.getColumnCount();
            
            //StringBuilder result = new StringBuilder();
            //result.append("SUCCESS");
            
            ArrayList<String> result = new ArrayList<String>();
            StringBuilder sb = new StringBuilder();
            
            sb = new StringBuilder();
            for(int i=1; i<=columnsCount; i++) {
                    sb.append(rsmd.getColumnLabel(i).trim());
                    if(i<columnsCount) {
                            sb.append(",");
                    }
            }
            result.add(sb.toString());
            
            while(rs.next()) {
                    sb = new StringBuilder();
                    for(int i=1; i<=columnsCount; i++) {
                            if(rs.getString(i) != null) {
                                    sb.append(rs.getString(i).trim());
                            }
                            if(i<columnsCount) {
                                    sb.append(",");
                            }
                    }
                    result.add(sb.toString());
            }
            stmt.close();
            stmt = null;
            rs.close();
            rs = null;
            
            r.getWriter().println("SUCCESS"+result.size());
            for(String str : result) {
                    r.getWriter().println(str);
            }
		} catch(SQLException e) {
			System.err.println("Query " + r.getSqlQuery() + "\n FAILED");
			e.printStackTrace();
			r.getWriter().println("FAILED");
		}
		finally {
			if(stmt != null) {
				try {
					stmt.close();
				} catch (SQLException e) {
				}
			}
			if(rs != null) {
				try {
					rs.close();
				} catch (SQLException e) {
				}
			}
			if (stop_time == 0) {
				stop_time = System.currentTimeMillis();
			}
			r.getClientHandler().setQueryProcessingData(start_time, stop_time, host);
			synchronized(r.getClientHandler()) {
				r.getClientHandler().shouldSleep = false;
				r.getClientHandler().notify();
			}
		}
	}
	
	public void run() {
		this.setName("MiddleMan - Worker thread");
		try {
			Request r;
			while(!_terminate) {
				r = Q.poll(1, TimeUnit.SECONDS);
				if(r!=null) {
					DoRequest(r);
				}
			}
		} catch (InterruptedException e) {
			System.err.println("Worker was interrupted while waiting...");
			e.printStackTrace();
		} finally {
			DB.disconnect(connection);
		}
	}
}
